#pragma once
// hikvision
#include "MvCameraControl.h"
// std
#include <atomic>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
// opencv
#include <opencv2/opencv.hpp>
// project
#include "thread_safe_queue.hpp"

namespace qd::Device {

struct CameraData {
    cv::Mat img;
    std::chrono::system_clock::time_point timestamp;
};

class HikCamera {
    
public:
    // 设置时间戳获取函数
    using TimeDataType = std::chrono::system_clock::time_point();
    void set_func_get_time(const std::function<TimeDataType>& func) {
        get_time_ = func;
    }
    std::function<TimeDataType> get_time_;

    struct Parameters {
        double exposure_time; // 曝光时间
        double gain; // 增益
        double frame_rate; // 帧率
        bool enable_frame_rate; // 是否启用帧率控制
        std::string adc_bit_depth; // ADC位深
        std::string pixel_format; // 像素格式
        bool enable_DeviceSerialNumber; // 是否启用设备序列号
        std::string device_serial_number; // 设备序列号
        int cvt_quality;
    };

public:
    HikCamera();
    ~HikCamera();
    cv::Mat get_cv_img();
    CameraData get_camera_queue();

private:
    void* get_camera_handle(const Parameters& params);
    void set_hik_param(void* handle, const Parameters& params);
    void image_callback();

private:
    void* camera_handle_; // 相机句柄
    MV_FRAME_OUT out_frame_buffer_; // 图像缓存
    MV_CC_PIXEL_CONVERT_PARAM convert_param; // 像素格式转换参数结构体
    int nRet = MV_OK; // 函数返回值
    Parameters params_; // 相机参数
    std::thread daemon_thread_; // 守护线程
    tools::ThreadSafeQueue<CameraData> queue_; // 图像队列
    std::atomic<bool> running_;
};

} // namespace qd::Device
